package net.sf.rose.business.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.sql.Statement;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import net.sf.rose.business.bean.base.FileBean;
import net.sf.rose.business.bean.database.FieldMetaBean;
import net.sf.rose.business.bean.database.LinkMetaBean;
import net.sf.rose.business.bean.database.TableMetaBean;
import net.sf.rose.business.service.function.Jdbc;
import net.sf.rose.exception.SystemErrorCode;
import net.sf.rose.exception.SystemException;
import net.sf.rose.jdbc.KeyGenerator;
import net.sf.rose.jdbc.GenericDAO;
import net.sf.rose.jdbc.QueryBeanSQL;
import net.sf.rose.jdbc.UserBean;
import net.sf.rose.jdbc.service.DataBaseFactory;
import net.sf.rose.jdbc.service.Service;
import net.sf.rose.util.DataUtil;
import net.sf.rose.util.DateUtil;

import org.apache.log4j.Logger;
import org.simpleframework.xml.ElementMap;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

/**
 * @author fengjian
 * @since 2014/05/25
 */
public class DataBaseService implements Serializable {

	private static final long serialVersionUID = 1L;

	private static Logger logger = Logger.getLogger(DataBaseService.class);

	/** 存储在数据库中的名称 */
	private static String NAME = "database_meta";

	/** 存储在数据库中的分类名称 */
	private static String SORT = "config";

	/** 本类的单例 */
	private static DataBaseService service = null;
	
	/** 数据类的单例 */
	private static FileBean fileBean = null;

	static {
		Service s = DataBaseFactory.getService();
		UserBean user = new UserBean();
		user.setUserName("system");
		s.setUser(user);
		GenericDAO dao = new GenericDAO(s);
		QueryBeanSQL query = new QueryBeanSQL(s);
		fileBean = new FileBean();
		fileBean.setCode(NAME);
		fileBean.setFileSort(SORT);
		try {
			query.createListSql(fileBean);
			Object obj = dao.load(query);
			if (obj != null) {
				fileBean = (FileBean) obj;
				InputStream in = fileBean.getFile();
				if (in != null) {
					Serializer serializer = new Persister();
					service = serializer.read(DataBaseService.class, in);
					service.initial();
					logger.info("成功地从数据库中读取了数据字典！");
				}
			}
			if (service == null) {
				service = new DataBaseService();
				logger.info("数据字典初始化...");
			}
		} catch (SystemException e) {
			logger.error("数据字典初始化从数据库读取时操作失败！", e);
			throw e;
		} catch (Exception e) {
			String message = "数据字典初始化失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		} finally {
			s.close();
		}
	}

	/**
	 * 
	 */
	public static void save(UserBean user) {
		Service s = DataBaseFactory.getService();
		GenericDAO dao = new GenericDAO(s);
		QueryBeanSQL query = new QueryBeanSQL(s);
		try {
			Serializer serializer = new Persister();
			File file = new File(System.getenv("TEMP"), KeyGenerator.getUID());
			serializer.write(service, file);
			InputStream in = new FileInputStream(file);
			fileBean.setFile(in);
			if (fileBean.getFileID() == null) {
				fileBean.setFileID(KeyGenerator.getUID());
				fileBean.setCreateUser(user.getUserName());
				fileBean.setCreateTime(DateUtil.getTimestamp());
				query.createInsertSql(fileBean);
			} else {
				fileBean.setUpdateUser(user.getUserName());
				fileBean.setUpdateTime(DateUtil.getTimestamp());
				query.createUpdateSql(fileBean);
			}
			dao.update(query);
			s.commit();
		} catch (SystemException e) {
			logger.error("数据字典保存至数据库操作失败！", e);
			throw e;
		} catch (Exception e) {
			String message = "数据字典保存失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		} finally {
			s.close();
		}
	}

	/**
	 * 
	 */
	public static void input(InputStream in) {
		try {
			if (in != null) {
				Serializer serializer = new Persister();
				service = serializer.read(DataBaseService.class, in);
				service.initial();
				logger.info("成功地从导入文件中读取了数据字典！");
			}
		} catch (Exception e) {
			String message = "数据字典导入失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		}
	}

	/**
	 * 
	 */
	public static File output() {
		try {
			Serializer serializer = new Persister();
			File file = new File(System.getenv("TEMP"), KeyGenerator.getUID());
			serializer.write(service, file);
			return file;
		} catch (Exception e) {
			String message = "数据字典导出失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		}
	}

	public static DataBaseService getService() {
		return service;
	}
	
	public Map<String, TableMetaBean> getAll() {
		return tables;
	}

	public void addTableMetaBean(TableMetaBean bean) {
		tables.put(bean.getName(), bean);
		this.initialLink(bean);
	}

	private void initial() {
		for (TableMetaBean bean : tables.values()) {
			this.initialLink(bean);
		}
	}

	private void initialLink(TableMetaBean bean) {
		for (FieldMetaBean f : bean.getFields()) {
			if (f.getLink() != null) {
				LinkMetaBean link = f.getLink();
				link.setSourceTable(bean);
				link.setSourceField(f);
				TableMetaBean table = tables.get(link.getTable());
				FieldMetaBean field = table.getFieldBean(link.getField());
				link.setTargetTable(table);
				link.setTargetField(field);
			}
		}
	}

	/** 所有定义 */
	@ElementMap(required = false)
	private Map<String, TableMetaBean> tables = new LinkedHashMap<String, TableMetaBean>();

	/** 所有定义 */
	@ElementMap(required = false)
	private Map<String, TableMetaBean> tables_bak = new LinkedHashMap<String, TableMetaBean>();

	public Map<String, TableMetaBean> getTables() {
		return tables;
	}

	public void setTables(Map<String, TableMetaBean> tables) {
		this.tables = tables;
	}

	public TableMetaBean getTable(String tableName) {
		return tables.get(tableName);
	}

	public void remove(String tableName) {
		tables.remove(tableName);
	}

	private List<String> sqls = null;
	
	/**
	 * 创建数据库更新SQL语句列表
	 */
	public List<String> createDatabaseUpdateSql() {
		Jdbc jdbc = DBMetaService.getService().getJdbcBean();
		sqls = jdbc.getUpdateSql(tables, tables_bak);
		return sqls;
	}

	/**
	 * 创建数据库更新SQL语句列表
	 */
	public List<String> getDatabaseUpdateSql() {
		return sqls;
	}

	/**
	 * 执行数据库更新SQL语句列表
	 */
	@SuppressWarnings("unchecked")
	public void executeDatabaseUpdateSql(UserBean user) {
		if(sqls == null || sqls.size() == 0) return;
		Service s = DataBaseFactory.getService();
		try {
			Statement stmt = s.getConnection().createStatement();
			for (String sql : sqls) {
				if (sql != null) {
					stmt.execute(sql);
				}
			}
			s.commit();
			tables_bak = ((Map<String, TableMetaBean>) DataUtil.getClone(tables));
			save(user);
		} catch (Exception e) {
			String message = "数据表结构更新失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		} finally {
			s.close();
		}
	}
}
